package ru.bragnikita.utils.logexplorer.web;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.bragnikita.utils.logexplorer.logic.FileSystemInterface;
import ru.bragnikita.utils.logexplorer.logic.mock.FileSystemModificationException;
import ru.bragnikita.utils.logexplorer.model.FileWithContent;

import javax.enterprise.context.RequestScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.*;

/**
 * @author Nikita.Brazhnikov
 */
@Named("file_edit")
@RequestScoped
public class EditFileBean {

	private static final Logger logger = LoggerFactory.getLogger(EditFileBean.class);

	@Inject
	private FileSystemInterface fs;

	private String filePath;

	private String fileName;

	private String textContent;

	private String encoding = "UTF-8";

	private boolean availableToSave = false;

	private String textMode = "text/plain";

	public boolean init() {
		if (StringUtils.isEmpty(filePath)) {
			logger.error("File is not selected");
			final String message = "File is not selected";
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message));
			return false;
		} else {
			logger.debug("Request for file editing, file is {}", filePath);
			fileName = new File(filePath).getName();
			textMode = ConvertationUtils.getAppropriateMimeType(filePath);
			if (encoding == null)
				encoding = "UTF-8";
			return true;
		}
	}

	private void loadFile() throws Exception {

		final FileWithContent content = fs.getFileContent(filePath);
		long size = content.getLength();
		logger.debug("File size is {}", size);
		if (size > Integer.MAX_VALUE) {
			throw new Exception("Files with length more than 2 Gb are not supported");
		}
		logger.debug("Content encoding is {}", encoding);
		Reader fileReader = new InputStreamReader(content.getContentStream(), encoding);
		StringWriter writer = new StringWriter(2 * new Long(size).intValue());
		IOUtils.copy(fileReader, writer);
		textContent = writer.toString();
		logger.debug("File content sample is ", StringUtils.abbreviate(textContent, 100));
		availableToSave = true;
	}

	public void save() {
		logger.debug("Saving {}", filePath);
		if (textContent == null)
			return;
		String errorMessage = null;
		try {
			byte[] contentBytes = textContent.getBytes(encoding);
			fs.saveFileContent(filePath, new ByteArrayInputStream(contentBytes));
			logger.debug("Successfully saved {}", filePath);
		} catch (UnsupportedEncodingException e) {
			logger.error("", e);
			errorMessage = e.getMessage();
		} catch (FileSystemModificationException e) {
			logger.error("", e);
			errorMessage = e.getMessage();
		}
		if (errorMessage == null) {
			final String fullMessage = String.format("%s successfully saved", fileName);
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Successfully saved", fullMessage));
		} else {
			final String fullMessage = String.format("Saving was failed: %s", errorMessage);
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Failed", fullMessage));
		}
	}

	public void reload() {
		if (init()) {
			try {
				logger.debug("Loading content of {}", filePath);
				loadFile();
			} catch (Exception e) {
				logger.error("Can not load file content", e);
				textContent = null;
				final String message = e.getMessage();
				FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message));
			}
		}
	}


	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public String getFilePath() {
		return filePath;
	}

	public void setFilePath(String filePath) {
		this.filePath = filePath;
	}

	public String getTextContent() {
		return textContent;
	}

	public void setTextContent(String textContent) {
		this.textContent = textContent;
	}

	public boolean isAvailableToSave() {
		return availableToSave;
	}

	public String getEncoding() {
		return encoding;
	}

	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}

	public String getTextMode() {
		return textMode;
	}

	public void setTextMode(String textMode) {
		this.textMode = textMode;
	}
}
